// =================================================================================================
// ADOBE SYSTEMS INCORPORATED
// Copyright 2006 Adobe Systems Incorporated
// All Rights Reserved
//
// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
// of the Adobe license agreement accompanying it.
// =================================================================================================

import XMPDateTime  from './XMPDateTime';
import XMPException from './XMPException';
import XMPDateTimeImpl from './impl/XMPDateTimeImpl';

/**
 * A factory to create <code>XMPDateTime</code>-instances from a <code>Calendar</code> or an
 * ISO 8601 string or for the current time.
 */
interface TimeZone {
    timeZone: string;
}

export default  class XMPDateTimeFactory {
    /** The UTC TimeZone */
    private static readonly UTC: TimeZone = { timeZone: 'UTC' };

    /**
     * Creates an <code>XMPDateTime</code> from a <code>Calendar</code>-object.
     * 
     * @param calendar a <code>Calendar</code>-object.
     * @return An <code>XMPDateTime</code>-object.
     */
    public static createFromCalendar(calendar: ESObject): XMPDateTime {
        return new XMPDateTimeImpl(calendar);
    }

    /**
     * Creates an empty <code>XMPDateTime</code>-object.
     * @return Returns an <code>XMPDateTime</code>-object.
     */
    public static createEmpty(): XMPDateTime {
        return new XMPDateTimeImpl();
    }

    /**
     * Creates an <code>XMPDateTime</code>-object from initial values.
     * @param year years
     * @param month months from 1 to 12<br>
     * <em>Note:</em> Remember that the month in {@link Calendar} is defined from 0 to 11.
     * @param day days
     * @return Returns an <code>XMPDateTime</code>-object.
     */
    public static createDate(year: number, month: number, day: number): XMPDateTime {
        const dt: XMPDateTime = new XMPDateTimeImpl();
        dt.setYear(year);
        dt.setMonth(month);
        dt.setDay(day);
        return dt;
    }

    /**
     * Creates an <code>XMPDateTime</code>-object from initial values.
     * @param year years
     * @param month months from 1 to 12<br>
     * <em>Note:</em> Remember that the month in {@link Calendar} is defined from 0 to 11.
     * @param day days
     * @param hour hours
     * @param minute minutes
     * @param second seconds
     * @param nanoSecond nanoseconds 
     * @return Returns an <code>XMPDateTime</code>-object.
     */
    public static create(year: number, month: number, day: number, 
        hour: number, minute: number, second: number, nanoSecond: number): XMPDateTime {
        const dt: XMPDateTime = new XMPDateTimeImpl();
        dt.setYear(year);
        dt.setMonth(month);
        dt.setDay(day);
        dt.setHour(hour);
        dt.setMinute(minute);
        dt.setSecond(second);
        dt.setNanoSecond(nanoSecond);
        return dt;
    }

    /**
     * Creates an <code>XMPDateTime</code> from an ISO 8601 string.
     * 
     * @param strValue The ISO 8601 string representation of the date/time.
     * @return An <code>XMPDateTime</code>-object.
     * @throws XMPException When the ISO 8601 string is non-conform
     */
    public static createFromISO8601(strValue: string): XMPDateTime {
        return new XMPDateTimeImpl(strValue);
    }

    /**
     * Obtain the current date and time.
     * 
     * @return Returns The returned time is UTC, properly adjusted for the local time zone. The
     *         resolution of the time is not guaranteed to be finer than seconds.
     */
    public static getCurrentDateTime(): XMPDateTime {
        return new XMPDateTimeImpl(new Date());
    }

    /**
     * Sets the local time zone without touching any other Any existing time zone value is replaced,
     * the other date/time fields are not adjusted in any way.
     * 
     * @param dateTime the <code>XMPDateTime</code> variable containing the value to be modified.
     * @return Returns an updated <code>XMPDateTime</code>-object.
     */
    public static setLocalTimeZone(dateTime: XMPDateTime): XMPDateTime {
        const cal: ESObject = dateTime.getCalendar();
        // 在ArkTS中使用本地时区
        return new XMPDateTimeImpl(cal);
    }

    /**
     * Make sure a time is UTC. If the time zone is not UTC, the time is
     * adjusted and the time zone set to be UTC.
     * 
     * @param dateTime
     *            the <code>XMPDateTime</code> variable containing the time to
     *            be modified.
     * @return Returns an updated <code>XMPDateTime</code>-object.
     */
    public static convertToUTCTime(dateTime: XMPDateTime): XMPDateTime {
        const timeInMillis: number = dateTime.getCalendar().getTimeInMillis ? 
            dateTime.getCalendar().getTimeInMillis() : 
            dateTime.getCalendar().getTime().getTime();
        const cal: Date = new Date(timeInMillis);
        return new XMPDateTimeImpl(cal);
    }

    /**
     * Make sure a time is local. If the time zone is not the local zone, the time is adjusted and
     * the time zone set to be local.
     * 
     * @param dateTime the <code>XMPDateTime</code> variable containing the time to be modified.
     * @return Returns an updated <code>XMPDateTime</code>-object.
     */
    public static convertToLocalTime(dateTime: XMPDateTime): XMPDateTime {
        const timeInMillis: number = dateTime.getCalendar().getTimeInMillis ? 
            dateTime.getCalendar().getTimeInMillis() : 
            dateTime.getCalendar().getTime().getTime();
        const cal: Date = new Date(timeInMillis);
        return new XMPDateTimeImpl(cal);
    }
}